[GitHub Actions] npm-auditで脆弱性が検出されれば実行をFailさせる
こんにちは、CX事業本部 IoT事業部の若槻です。
今回は、GitHub Actionsでnpm-auditコマンドの実行で脆弱性があれば実行をFailさせるWorkflowを作ってみます。
このような仕組みを作るならDependabotやSnykを使っても良さそうですが、使ってみたいactionsもあったので勉強がてら自分で仕組みを作ってみました。
npm auditとは
npm audit
コマンドを使用すると、プロジェクト内のDependencyをスキャンして、レジストリに問い合わせて脆弱性が無いかをチェックしたり、自動修正したりすることができます。
またGitHub Actionsでnpm-auditを実行する上で役立ちそうなオプションとしてaudit-levelとomitがあります。
audit-levelオプション
npm-auditは検出した脆弱性を緊急度に応じて次の4段階でレベル分けします。
- low
- moderate
- high
- critical
既定では、いずれのレベルの脆弱性が検出されてもnon-zero exit codeとなります。下記ではレベルmoderate
の脆弱性が検出されてexit codeが1
となっています。
$ npm audit # npm audit report log4js <6.4.0 Severity: moderate Incorrect Default Permissions in log4js - https://github.com/advisories/GHSA-82v2-mx6x-wq7q No fix available node_modules/log4js jest-logger * Depends on vulnerable versions of log4js node_modules/jest-logger 2 moderate severity vulnerabilities Some issues need review, and may require choosing a different dependency. $ echo $? 1
audit-levelオプションを指定すると、指定した以上のレベルの脆弱性の検出時のみnon-zero exit codeとすることができます。先程のDependencyに対してaudit-levelオプションを指定して実行すると次のようになります。
$ npm audit --audit-level high $ echo $? 0 $ npm audit --audit-level moderate $ echo $? 1
このオプションを指定すれば、緊急度が高く迅速な修正が必要な脆弱性が検出された時のみWorkflow実行をFailさせて通知をする運用が可能です。
omitオプション
npm-auditでは既定ではDependencyとDevDepndencyの両方に対して脆弱性検出を行います。
omitオプションでdev
を指定すると、Dependencyの方のみに対して脆弱性検出を行います。
$ npm audit --omit=dev
ちなみに--production
を指定しても同じ結果が得られますが、--omit=dev
の方を使うように促されます。
DevDepndencyがプロダクトに使われないことが明確であるプロジェクトであれば、このオプションを指定してDependencyのみ脆弱性検出の対象とする運用も考えられます。
やってみる
次のWorkflowをGitHub Actionsで作ってみます。
- npm-auditを定期実行して、脆弱性があればFailさせる(通知をする)
実装時に脆弱性が検出されなかったDependencyでしばらく経ってから深刻な脆弱性が発見/発表される場合もあるので、継続的な監視が大切です。
定期実行
Workflowを定期実行させたい場合は、scheduleイベントを使用します。
次のようなWorkflowで試してみます。npm-auditの実行で--audit-level high
としています。
on: schedule: - cron: "0 0 * * 0" #日本時間 毎週月曜日 朝9時00分 jobs: job1: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v3 - name: Audit Dependency run: | npm audit --audit-level high --omit=dev
Workflowが実行されると、レベルmoderate
の脆弱性が検出されていますが、audit-levelの指定によりzero exit codeとなりFailはしていません。
次にnpm-auditの実行を--audit-level moderate
とします。
- name: Audit Dependency run: | npm audit --audit-level high --omit=dev
Workflowが実行されると、先程と同じくレベルmoderate
の脆弱性が検出されて、WorkflowがFailしました。
Failによるメール通知も届きました。
この通知を受けたらDependencyを修正する対応を取る運用とすれば良さそうです。
注意点
ちなみに注意点として、scheduleイベントは予定時刻から数十分近くずれることがあるそうです。私が試した際にも予定時刻になっても全然実行されなくて焦りました…。
さらなる改善をするなら
Fail時にメールだけでなくSlack通知をしたいなら下記のSlack社公式のActionを使えば実現できます。
またPull Request作成も自動化したいなら下記のActionが使えそうです。(Dependencyの修正は自分で行う必要があり)
またWorkflow内でのジョブのFailの検知はneeds.<job-id>.result == 'failure'
で出来るようです。
おわりに
GitHub Actionsでnpm-auditコマンドの実行で脆弱性があれば実行をFailさせるWorkflowを作ってみました。
繰り返しになりますが、ソフトウェアではリリースからしばらく経ってから深刻な脆弱性が発見/発表される場合があるので、継続的な脆弱性監視の実施と、脆弱性を検出された際に迅速な対応ができる体制を持つことが大切です。クリティカルなシステムでは今回のような仕組み(もしくはDependabotやSnykなどの既成サービス)を必ず構築/運用するようにしましょう。
参考
以上